home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 684 / 684.xpi / chrome / fireftp.jar / content / js / local / localTree.js < prev   
Text File  |  2009-09-28  |  46KB  |  1,212 lines

  1. var localTree = {
  2.   data                    : new Array(),
  3.   displayData             : new Array(),
  4.   rowCount                : 0,
  5.   localSize               : 0,
  6.   localAvailableDiskSpace : 0,
  7.   searchMode              : 0,
  8.   isEditing               : false,
  9.   editType                : "",
  10.   editParent              : null,
  11.   rememberSort            : null,
  12.  
  13.   getParentIndex      : function(row)               { return -1; },
  14.   getLevel            : function(row)               { return 0;  },
  15.   getRowProperties    : function(row, props)        { },
  16.   getColumnProperties : function(colid, col, props) { },
  17.   isContainer         : function(row)               { return false; },
  18.   isSeparator         : function(row)               { return false; },
  19.   isSorted            : function(row)               { return false; },
  20.   setTree             : function(treebox)           { this.treebox = treebox; },
  21.  
  22.   getCellText         : function(row, column)       {                                           // text for the files
  23.     if (row >= 0 && row < this.data.length) {
  24.       switch(column.id) {
  25.         case "localname":
  26.           return this.searchMode == 2 ? this.displayData[row].path : this.displayData[row].leafName;
  27.         case "localsize":
  28.           return this.displayData[row].fileSize;
  29.         case "localdate":
  30.           return this.displayData[row].date;
  31.         case "localtype":
  32.           return this.displayData[row].extension;
  33.         case "localattr":
  34.           return this.displayData[row].attr;
  35.         default:
  36.           return " ";
  37.       }
  38.     }
  39.  
  40.     return "";
  41.   },
  42.  
  43.   getImageSrc  : function(row, col)  {
  44.     return row >= 0 && row < this.data.length && col.id == "localname" && this.displayData[row].icon ? this.displayData[row].icon : "";
  45.   },
  46.  
  47.   cycleHeader : function(col) {
  48.     var sortDirection = col.element.getAttribute("sortDirection") == "descending"
  49.                      || col.element.getAttribute("sortDirection") == "natural"  ? "ascending" : "descending";
  50.     $('localname').setAttribute("sortDirection", "natural");
  51.     $('localsize').setAttribute("sortDirection", "natural");
  52.     $('localdate').setAttribute("sortDirection", "natural");
  53.     $('localtype').setAttribute("sortDirection", "natural");
  54.     $('localattr').setAttribute("sortDirection", "natural");
  55.     col.element.setAttribute(   "sortDirection", sortDirection);
  56.     this.sort();
  57.   },
  58.  
  59.   getCellProperties : function(row, col, props)   {
  60.     if (row >= 0 && row < this.data.length && this.data[row]) {
  61.       if (col.id == "localname") {
  62.         if (this.displayData[row].isDirectory) {
  63.           props.AppendElement(gAtomService.getAtom("isFolder"));
  64.         } else if (this.displayData[row].isSymlink) {
  65.           props.AppendElement(gAtomService.getAtom("isLink"));
  66.         }
  67.  
  68.         props.AppendElement(gAtomService.getAtom("nameCol"));
  69.       }
  70.  
  71.       if (dragObserver.overName && this.displayData[row].isDirectory) {
  72.         props.AppendElement(gAtomService.getAtom("overName"));
  73.       }
  74.  
  75.       if (this.displayData[row].isHidden) {
  76.         props.AppendElement(gAtomService.getAtom("hidden"));
  77.       }
  78.  
  79.       if (this.displayData[row].isCut) {
  80.         props.AppendElement(gAtomService.getAtom("cut"));
  81.       }
  82.     }
  83.   },
  84.  
  85.   // ****************************************************** updateView ***************************************************
  86.  
  87.   updateView : function(files) {
  88.     var localTreeItems = new Array();
  89.  
  90.     if (!files) {
  91.       this.searchMode = 0;
  92.       gLocalTreeChildren.removeAttribute('search');
  93.  
  94.       try {
  95.         this.localSize               = 0;
  96.         var dir                      = localFile.init(gLocalPath.value);
  97.         this.localAvailableDiskSpace = parseSize(dir.diskSpaceAvailable);                       // get local disk size
  98.         var entries                  = dir.directoryEntries;
  99.  
  100.         while (entries.hasMoreElements()) {
  101.           var file        = entries.getNext().QueryInterface(Components.interfaces.nsILocalFile);
  102.           var isException = false;
  103.  
  104.           for (var x = 0; x < localDirTree.exceptions.length; ++x) {
  105.             if (gSlash == "/") {
  106.               isException  = localDirTree.exceptions[x].path               == file.path;
  107.             } else {
  108.               isException  = localDirTree.exceptions[x].path.toLowerCase() == file.path.toLowerCase();
  109.             }
  110.  
  111.             if (isException) {
  112.               break;
  113.             }
  114.           }
  115.  
  116.           if (file.exists() && localFile.testSize(file) && (!file.isHidden() || gFtp.hiddenMode || isException)) {
  117.             this.localSize += file.fileSize;
  118.             localTreeItems.push(file);
  119.           }
  120.         }
  121.  
  122.         this.localSize = parseSize(this.localSize);                                             // get directory size
  123.         this.data      = localTreeItems;                                                        // update localTree
  124.       } catch (ex) {
  125.         debug(ex);
  126.         this.data        = new Array();
  127.         this.displayData = new Array();
  128.         this.treebox.rowCountChanged(0, -this.rowCount);
  129.         this.rowCount = this.data.length;
  130.         this.treebox.rowCountChanged(0, this.rowCount);
  131.         this.mouseOver(null);
  132.         error(gStrbundle.getString("noPermission"));
  133.         return;
  134.       }
  135.     } else {
  136.       if (this.localSize != -1) {
  137.         this.data        = new Array();
  138.         this.displayData = new Array();
  139.         this.treebox.rowCountChanged(0, -this.rowCount);
  140.  
  141.         this.rememberSort = { cols : ["localname", "localsize", "localdate", "localtype", "localattr"],
  142.                               vals : [$('localname').getAttribute("sortDirection"),
  143.                                       $('localsize').getAttribute("sortDirection"),
  144.                                       $('localdate').getAttribute("sortDirection"),
  145.                                       $('localtype').getAttribute("sortDirection"),
  146.                                       $('localattr').getAttribute("sortDirection")] };
  147.       }
  148.  
  149.       files.sort(compareName);
  150.  
  151.       for (var x = 0; x < files.length; ++x) {
  152.         this.data.push(files[x]);
  153.       }
  154.  
  155.       this.localSize  = -1;
  156.       this.searchMode = this.searchMode ? this.searchMode : (gSearchRecursive ? 2 : 1);
  157.       gLocalTreeChildren.setAttribute('search', true);
  158.     }
  159.  
  160.     this.sort(files);
  161.  
  162.     var index = localDirTree.indexOfPath(gLocalPath.value);                                     // select directory in localDirTree
  163.     localDirTree.selection.select(index);
  164.     localDirTree.treebox.ensureRowIsVisible(index);
  165.  
  166.     if (this.data.length && !files) {
  167.       this.selection.select(0);                                                                 // select first element in localTree
  168.     }
  169.  
  170.     this.mouseOver(null);
  171.  
  172.     if (files) {
  173.       return;
  174.     }
  175.  
  176.     var anyFolders = false;                                                                     // see if the folder has any subfolders
  177.     for (var x = 0; x < this.data.length; ++x) {
  178.       if (this.data[x].isDirectory()) {
  179.         anyFolders = true;
  180.         break;
  181.       }
  182.     }
  183.  
  184.     if (!anyFolders) {                                                                          // and if there are no subfolders then update our tree
  185.       if (localDirTree.data[index].open) {                                                      // if localDirTree is open
  186.         localDirTree.toggleOpenState(index);
  187.       }
  188.  
  189.       localDirTree.data[index].empty    = true;
  190.       localDirTree.data[index].open     = false;
  191.       localDirTree.data[index].children = null;
  192.  
  193.       for (var x = 0; x < localDirTree.dirtyList.length; ++x) {
  194.         if (localDirTree.dirtyList[x] == gLocalPath.value) {
  195.           localDirTree.dirtyList.splice(x, 1);
  196.           break;
  197.         }
  198.       }
  199.     } else if (anyFolders && localDirTree.data[index].empty) {
  200.       localDirTree.data[index].empty    = false;
  201.     }
  202.  
  203.     localDirTree.treebox.invalidateRow(index);
  204.   },
  205.  
  206.   sort : function(files) {
  207.     if (!files) {
  208.       if (this.rememberSort) {
  209.         for (var x = 0; x < this.rememberSort.cols.length; ++x) {
  210.           $(this.rememberSort.cols[x]).setAttribute("sortDirection", this.rememberSort.vals[x]);
  211.         }
  212.  
  213.         this.rememberSort = null;
  214.       }
  215.  
  216.       this.sortHelper($('localname'), this.searchMode == 2 ? directorySort2 : compareName);
  217.       this.sortHelper($('localsize'), compareSize);
  218.       this.sortHelper($('localdate'), compareDate);
  219.       this.sortHelper($('localtype'), compareType);
  220.       this.sortHelper($('localattr'), compareLocalAttr);
  221.  
  222.       this.displayData = new Array();
  223.     } else {
  224.       $('localname').setAttribute("sortDirection", "natural");
  225.       $('localsize').setAttribute("sortDirection", "natural");
  226.       $('localdate').setAttribute("sortDirection", "natural");
  227.       $('localtype').setAttribute("sortDirection", "natural");
  228.       $('localattr').setAttribute("sortDirection", "natural");
  229.     }
  230.  
  231.     var start = files ? this.data.length - files.length : 0;
  232.  
  233.     for (var row = start; row < this.data.length; ++row) {
  234.       this.displayData.push({ leafName    : this.data[row].leafName,
  235.                               fileSize    : this.getFormattedFileSize(row),
  236.                               date        : this.getFormattedDate(row),
  237.                               extension   : this.data[row].isDirectory() ? "" : this.getExtension(this.data[row].leafName),
  238.                               attr        : this.data[row].permissions   ? this.convertPermissions(this.data[row].isHidden(), this.data[row].permissions) : "",
  239.                               icon        : this.getFileIcon(row),
  240.                               path        : this.data[row].path,
  241.                               isDirectory : this.data[row].isDirectory(),
  242.                               isSymlink   : this.data[row].isSymlink(),
  243.                               isHidden    : this.data[row].isHidden() });
  244.     }
  245.  
  246.     if (files) {
  247.       this.rowCount = this.data.length;
  248.       this.treebox.rowCountChanged(start, files.length);
  249.     } else {
  250.       this.treebox.rowCountChanged(0, -this.rowCount);
  251.       this.rowCount = this.data.length;
  252.       this.treebox.rowCountChanged(0, this.rowCount);
  253.     }
  254.   },
  255.  
  256.   sortHelper : function(el, sortFunc) {
  257.     if (el.getAttribute("sortDirection") && el.getAttribute("sortDirection") != "natural") {
  258.       this.data.sort(sortFunc);
  259.  
  260.       if (!gPrefs.getBoolPref("localsortfix")) {   // blah, fix dumb mistake that changed descending into ascending
  261.         el.setAttribute("sortDirection", "ascending");
  262.         gPrefs.setBoolPref("localsortfix", true);
  263.       }
  264.  
  265.       if (el.getAttribute("sortDirection") == "descending") {
  266.         this.data.reverse();
  267.       }
  268.     }
  269.   },
  270.  
  271.   getFormattedFileSize : function(row) {
  272.     if (this.data[row].isDirectory()) {
  273.       return "";
  274.     }
  275.  
  276.     if (this.data[row].fileSize == 0) {
  277.       return gBytesMode ? "0  " : gStrbundle.getFormattedString("kilobyte", ["0"]) + "  ";
  278.     }
  279.  
  280.     if (gBytesMode) {
  281.       return commas(this.data[row].fileSize) + "  ";
  282.     }
  283.  
  284.     return gStrbundle.getFormattedString("kilobyte", [commas(Math.ceil(this.data[row].fileSize / 1024))]) + "  ";
  285.   },
  286.  
  287.   getFormattedDate : function(row) {
  288.     var date = new Date(this.data[row].lastModifiedTime);
  289.  
  290.     if ((new Date()).getFullYear() > date.getFullYear()) {                                      // if not current year, display old year
  291.       return gMonths[date.getMonth()] + ' ' + date.getDate() + ' ' + date.getFullYear();
  292.     }
  293.  
  294.     var time = date.toLocaleTimeString();                                                       // else display time
  295.     var ampm = time.indexOf('AM') != - 1 ? ' AM' : (time.indexOf('PM') != -1 ? ' PM' : '');
  296.     return gMonths[date.getMonth()] + ' ' + date.getDate() + ' ' + time.substring(0, time.lastIndexOf(':')) + ampm;
  297.   },
  298.  
  299.   getExtension : function(leafName) {
  300.     return leafName.lastIndexOf(".") != -1 ? leafName.substring(leafName.lastIndexOf(".") + 1, leafName.length).toLowerCase() : "";
  301.   },
  302.  
  303.   convertPermissions : function(hidden, permissions) {
  304.     if (gSlash == "\\") {                                                                       // msdos
  305.       var returnString = "";
  306.  
  307.       if (permissions == 438) {                                                                 // Normal file  (666 in octal)
  308.         returnString = gStrbundle.getString("normalFile");
  309.       } else if (permissions == 511) {                                                          // Executable file (777 in octal)
  310.         returnString = gStrbundle.getString("executableFile");
  311.       } else if (permissions == 292) {                                                          // Read-only (444 in octal)
  312.         returnString = gStrbundle.getString("readOnlyFile");
  313.       } else if (permissions == 365) {                                                          // Read-only and executable (555 in octal)
  314.         returnString = gStrbundle.getString("readOnlyExecutableFile");
  315.       } else {
  316.         returnString = " ";
  317.       }
  318.  
  319.       if (hidden) {
  320.         returnString += gStrbundle.getString("hiddenFile");
  321.       }
  322.  
  323.       return returnString;
  324.     } else {
  325.       permissions           = permissions.toString(8);
  326.  
  327.       if (gPlatform == 'mac') {
  328.         permissions         = permissions.substring(permissions.length - 4);
  329.       }
  330.  
  331.       permissions           = parseInt(permissions, 8);
  332.       var binary            = permissions.toString(2);
  333.       var permissionsString = "";
  334.  
  335.       for (var x = 0; x < 9; x += 3) {
  336.         permissionsString += binary.charAt(0 + x) == "1" ? "r" : "-";
  337.         permissionsString += binary.charAt(1 + x) == "1" ? "w" : "-";
  338.         permissionsString += binary.charAt(2 + x) == "1" ? "x" : "-";
  339.       }
  340.  
  341.       return permissionsString;
  342.     }
  343.   },
  344.  
  345.   getFileIcon : function(row) {
  346.     if (this.data[row].isDirectory() || this.data[row].isSymlink()) {
  347.       return "";
  348.     }
  349.  
  350.     var fileURI = gIos.newFileURI(this.data[row]);
  351.     return "moz-icon://" + fileURI.spec + "?size=16";                                           // thanks to alex sirota!
  352.   },
  353.  
  354.   // ************************************************** refresh *******************************************************
  355.  
  356.   refresh : function(skipLocalTree, skipDelay) {
  357.     if (localDirTree.data[localDirTree.selection.currentIndex].open) {                          // if localDirTree is open
  358.       localDirTree.toggleOpenState(localDirTree.selection.currentIndex);                        // close it up
  359.       localDirTree.data[localDirTree.selection.currentIndex].children = null;                   // reset its children
  360.       localDirTree.toggleOpenState(localDirTree.selection.currentIndex);                        // and open it up again
  361.     } else {
  362.       localDirTree.data[localDirTree.selection.currentIndex].empty    = false;                  // not empty anymore
  363.       localDirTree.data[localDirTree.selection.currentIndex].children = null;                   // reset its children
  364.       localDirTree.treebox.invalidateRow(localDirTree.selection.currentIndex);
  365.     }
  366.  
  367.     if (!skipLocalTree) {
  368.       if (skipDelay) {
  369.         this.updateView();
  370.       } else {
  371.         setTimeout("localTree.updateView()", 1000);                                             // update localTree, after a little bit
  372.       }
  373.     }
  374.   },
  375.  
  376.   // ****************************************************** file functions ***************************************************
  377.  
  378.   constructPath : function(parent, leafName) {
  379.     return parent + (parent.charAt(parent.length - 1) != gSlash ? gSlash : '') + leafName;
  380.   },
  381.  
  382.   launch : function() {
  383.     if (this.selection.count == 0) {
  384.       return;
  385.     }
  386.  
  387.     for (var x = 0; x < this.rowCount; ++x) {
  388.       if (this.selection.isSelected(x)) {
  389.         if (!localFile.verifyExists(this.data[x])) {
  390.           continue;
  391.         }
  392.  
  393.         localFile.launch(this.data[x]);
  394.       }
  395.     }
  396.   },
  397.  
  398.   openContainingFolder : function() {
  399.     if (this.selection.currentIndex < 0 || this.selection.currentIndex >= this.rowCount || !localFile.verifyExists(this.data[this.selection.currentIndex].parent)) {
  400.       return;
  401.     }
  402.  
  403.     localDirTree.changeDir(this.data[this.selection.currentIndex].parent.path);
  404.   },
  405.  
  406.   extract : function(toFolder) {
  407.     if (this.selection.count == 0) {
  408.       return;
  409.     }
  410.  
  411.     var files = new Array();
  412.  
  413.     for (var x = 0; x < this.rowCount; ++x) {
  414.       if (this.selection.isSelected(x)) {
  415.         if (!localFile.verifyExists(this.data[x])) {
  416.           continue;
  417.         }
  418.  
  419.         files.push(this.data[x]);
  420.       }
  421.     }
  422.  
  423.     for (var x = 0; x < files.length; ++x) {
  424.       var extension = this.getExtension(files[x].leafName);
  425.       if (extension != "zip" && extension != "jar" && extension != "xpi") {
  426.         continue;
  427.       }
  428.  
  429.       this.extractHelper(toFolder, files[x]);
  430.     }
  431.   },
  432.  
  433.   extractHelper : function(toFolder, file) {                                                    // code modified from
  434.     try {                                                                                       // http://xulfr.org/wiki/RessourcesLibs/lireExtraireZip
  435.       var origParent = gLocalPath.value;                                                        // since were doing threading, the parent path could change during extraction
  436.       ++gProcessing;
  437.       var zip        = Components.classes["@mozilla.org/libjar/zip-reader;1"].createInstance(Components.interfaces.nsIZipReader);
  438.       zip.open(file);
  439.  
  440.       var leafNameNoExt = file.leafName.lastIndexOf(".") != -1 ? file.leafName.substring(0, file.leafName.lastIndexOf("."))
  441.                                                                : file.leafName;
  442.       var localParent   = toFolder ? this.constructPath(file.parent.path, leafNameNoExt) : file.parent.path;
  443.       var folder        = localFile.init(localParent);
  444.  
  445.       if (!folder.exists()) {
  446.         folder.create(Components.interfaces.nsILocalFile.DIRECTORY_TYPE, 0755);
  447.       }
  448.  
  449.       var prompt  = true;
  450.       var skipAll = false;
  451.  
  452.       var entries = zip.findEntries("*");
  453.  
  454.       while (entries.hasMore()) {
  455.         var entry      = entries.getNext();
  456.         var destFolder = localFile.init(localParent);
  457.         var entrySplit = entry.split('/');
  458.  
  459.         for (var x = 0; x < entrySplit.length; ++x) {
  460.           if (x == entrySplit.length - 1 && entrySplit[x].length != 0) {
  461.             destFolder.append(entrySplit[x]);
  462.             var zipEntry = zip.getEntry(entry);
  463.  
  464.             if (destFolder.exists() && skipAll) {
  465.               break;
  466.             }
  467.  
  468.             if (destFolder.exists() && prompt) {                                                // ask nicely
  469.               var params = { response         : 0,
  470.                              fileName         : destFolder.path,
  471.                              resume           : true,
  472.                              replaceResume    : true,
  473.                              existingSize     : destFolder.fileSize,
  474.                              existingDate     : "",
  475.                              newSize          : zipEntry.realSize,
  476.                              newDate          : "",
  477.                              timerEnable      : false };
  478.  
  479.               window.openDialog("chrome://fireftp/content/confirmFile.xul", "confirmFile", "chrome,modal,dialog,resizable,centerscreen", params);
  480.  
  481.               if (params.response == 2) {
  482.                 prompt = false;
  483.               } else if (params.response == 3) {
  484.                 break;
  485.               } else if (params.response == 4 || params.response == 0) {
  486.                 --gProcessing;
  487.                 return;
  488.               } else if (params.response == 5) {
  489.                 skipAll = true;
  490.                 break;
  491.               }
  492.             }
  493.  
  494.             var innerEx = gFireFTPUtils.extract(zip, entry, destFolder);
  495.  
  496.             if (innerEx) {
  497.               throw innerEx;
  498.             }
  499.  
  500.             break;
  501.           }
  502.  
  503.           destFolder.append(entrySplit[x]);
  504.  
  505.           try {
  506.             if (!destFolder.exists()) {
  507.               destFolder.create(Components.interfaces.nsILocalFile.DIRECTORY_TYPE, 0755);
  508.             }
  509.           } catch (ex) { }
  510.         }
  511.       }
  512.  
  513.       zip.close();
  514.  
  515.       if (origParent == gLocalPath.value) {                                                     // since we're extracting on a separate thread make sure we're in the same directory on refresh
  516.         this.refresh();
  517.       } else {
  518.         localDirTree.addDirtyList(origParent);
  519.       }
  520.     } catch (ex) {
  521.       error(gStrbundle.getString("errorExtract"));
  522.       debug(ex);
  523.     } finally {
  524.       --gProcessing;
  525.     }
  526.   },
  527.  
  528.   create : function(isDir) {
  529.     if (this.searchMode == 2) {
  530.       return;
  531.     }
  532.  
  533.     this.data.push({        leafName    : "",
  534.                             fileSize    : "",
  535.                             date        : "",
  536.                             extension   : "",
  537.                             attr        : "",
  538.                             path        : "",
  539.                             isDir       : isDir,
  540.                             isDirectory : function() { return this.isDir },
  541.                             isSymlink   : function() { return false },
  542.                             isHidden    : false });
  543.     this.displayData.push({ leafName    : "",
  544.                             fileSize    : "",
  545.                             date        : "",
  546.                             extension   : "",
  547.                             attr        : "",
  548.                             icon        : isDir ? "" : "moz-icon://file?size=16",
  549.                             path        : "",
  550.                             isDirectory : isDir,
  551.                             isSymlink   : false,
  552.                             isHidden    : false });
  553.     ++this.rowCount;
  554.     this.treebox.rowCountChanged(this.rowCount - 1, 1);
  555.     this.treebox.ensureRowIsVisible(this.rowCount - 1);
  556.  
  557.     this.editType   = "create";
  558.     this.editParent = gLocalPath.value;
  559.     setTimeout("gLocalTree.startEditing(localTree.rowCount - 1, gLocalTree.columns['localname'])", 0);
  560.   },
  561.  
  562.   remove : function() {
  563.     if (this.selection.count == 0) {
  564.       return;
  565.     }
  566.  
  567.     var count = this.selection.count;
  568.     var files = new Array();
  569.  
  570.     for (var x = 0; x < this.rowCount; ++x) {
  571.       if (this.selection.isSelected(x)) {
  572.         if (!localFile.verifyExists(this.data[x])) {
  573.           continue;
  574.         }
  575.  
  576.         files.push(this.data[x]);
  577.       }
  578.     }
  579.  
  580.     var origParent = gLocalPath.value;                                                          // since were doing threading, the parent path could change during deleting
  581.     var prompt     = true;
  582.  
  583.     for (var x = 0; x < files.length; ++x) {
  584.       if (!localFile.remove(files[x], prompt, count)) {
  585.         break;
  586.       }
  587.  
  588.       prompt = false;
  589.     }
  590.  
  591.     if (origParent == gLocalPath.value) {                                                       // since we're deleting on a separate thread make sure we're in the same directory on refresh
  592.       this.refresh(false, true);
  593.     } else {
  594.       localDirTree.addDirtyList(origParent);
  595.     }
  596.   },
  597.  
  598.   rename : function() {
  599.     if (this.rowCount > 0 && this.selection.count > 0) {
  600.       if (this.selection.currentIndex < 0 || this.selection.currentIndex >= this.rowCount) {
  601.         this.selection.currentIndex = this.rowCount - 1;
  602.       }
  603.  
  604.       if (!localFile.verifyExists(this.data[this.selection.currentIndex])) {
  605.         return;
  606.       }
  607.  
  608.       this.displayData[this.selection.currentIndex].origLeafName = this.data[this.selection.currentIndex].leafName;
  609.       this.displayData[this.selection.currentIndex].origPath     = this.data[this.selection.currentIndex].path;
  610.  
  611.       if (this.searchMode == 2) {
  612.         this.displayData[this.selection.currentIndex].path = this.displayData[this.selection.currentIndex].leafName;
  613.         this.treebox.invalidateRow(this.selection.currentIndex);
  614.       }
  615.  
  616.       this.editType   = "rename";
  617.       this.editParent = gLocalPath.value;
  618.       gLocalTree.startEditing(this.selection.currentIndex, gLocalTree.columns["localname"]);
  619.     }
  620.   },
  621.  
  622.   isEditable : function(row, col) {
  623.     var canEdit = row >= 0 && row < this.data.length && col.id == "localname";
  624.     this.isEditing = canEdit;
  625.     return canEdit;
  626.   },
  627.  
  628.   setCellText : function(row, col, val) {
  629.     if (!this.isEditing || this.editParent != gLocalPath.value) {                               // for some reason, this is called twice - so we prevent this
  630.       return;
  631.     }
  632.  
  633.     this.isEditing = false;
  634.     if (this.editType == "rename") {
  635.       if (this.data[row].leafName == val) {
  636.         // do nothing
  637.       } else if (localFile.rename(this.data[row], val)) {
  638.         var rowDiff = this.treebox.getLastVisibleRow() - row;
  639.  
  640.         this.refresh(false, true);
  641.  
  642.         for (var x = 0; x < this.rowCount; ++x) {
  643.           if (this.data[x].leafName == val) {
  644.             this.selection.select(x);
  645.             this.treebox.ensureRowIsVisible(rowDiff + x - 1 < this.rowCount ? rowDiff + x - 1 : this.rowCount - 1);
  646.             break;
  647.           }
  648.         }
  649.       } else {
  650.         this.displayData[row].leafName = val;
  651.         this.treebox.invalidateRow(row);
  652.         setTimeout("gLocalTree.startEditing(" + row + ", gLocalTree.columns['localname'])", 0);
  653.       }
  654.     } else if (this.editType == "create") {
  655.       if (val) {
  656.         if (localFile.create(this.data[row].isDir, val)) {
  657.           this.refresh(false, true);
  658.  
  659.           for (var x = 0; x < this.rowCount; ++x) {
  660.             if (this.data[x].leafName == val) {
  661.               this.selection.select(x);
  662.               this.treebox.ensureRowIsVisible(x);
  663.               break;
  664.             }
  665.           }
  666.         } else {
  667.           this.data[row].leafName        = val;
  668.           this.displayData[row].leafName = val;
  669.           this.treebox.invalidateRow(row);
  670.           setTimeout("gLocalTree.startEditing(localTree.rowCount - 1, gLocalTree.columns['localname'])", 0);
  671.         }
  672.       } else {
  673.         --this.rowCount;
  674.         this.data.splice(this.rowCount, 1);
  675.         this.displayData.splice(this.rowCount, 1);
  676.         this.treebox.rowCountChanged(this.rowCount, -1);
  677.       }
  678.     }
  679.   },
  680.  
  681.   showProperties : function(recursive) {
  682.     if (this.rowCount == 0 || this.selection.count == 0) {
  683.       return;
  684.     }
  685.  
  686.     if (this.selection.currentIndex < 0 || this.selection.currentIndex >= this.rowCount) {
  687.       this.selection.currentIndex = this.rowCount - 1;
  688.     }
  689.  
  690.     if (this.selection.count > 1) {                                                             // multiple files
  691.       var files = new Array();
  692.  
  693.       for (var x = 0; x < this.rowCount; ++x) {
  694.         if (this.selection.isSelected(x)) {
  695.           if (!localFile.verifyExists(this.data[x])) {
  696.             continue;
  697.           }
  698.  
  699.           files.push(this.data[x]);
  700.         }
  701.       }
  702.  
  703.       var recursiveFolderData = { type: "local", nFolders: 0, nFiles: 0, nSize: 0 };
  704.  
  705.       for (var x = 0; x < files.length; ++x) {
  706.         if (!localFile.verifyExists(files[x])) {
  707.           continue;
  708.         }
  709.  
  710.         if (files[x].isDirectory()) {
  711.           ++recursiveFolderData.nFolders;
  712.  
  713.           if (recursive) {
  714.             this.getRecursiveFolderData(files[x], recursiveFolderData);
  715.           }
  716.         } else {
  717.           ++recursiveFolderData.nFiles;
  718.         }
  719.  
  720.         recursiveFolderData.nSize += files[x].fileSize;
  721.       }
  722.  
  723.       var params = { multipleFiles       : true,
  724.                      recursiveFolderData : recursiveFolderData };
  725.  
  726.       window.openDialog("chrome://fireftp/content/properties.xul", "properties", "chrome,modal,dialog,resizable,centerscreen", params);
  727.  
  728.       return;
  729.     }
  730.  
  731.     if (!localFile.verifyExists(this.data[this.selection.currentIndex])) {
  732.       return;
  733.     }
  734.  
  735.     var origParent = gLocalPath.value;                                                          // since were doing threading, the parent path could change
  736.  
  737.     if (localFile.showProperties(this.data[this.selection.currentIndex], recursive)) {
  738.       if (origParent == gLocalPath.value) {                                                     // since we're working on a separate thread make sure we're in the same directory on refresh
  739.         var single  = this.selection.count == 1 ? this.selection.currentIndex : -1;
  740.         var name    = this.data[this.selection.currentIndex].leafName;
  741.         var rowDiff = this.treebox.getLastVisibleRow() - single;
  742.  
  743.         this.refresh(false, true);
  744.  
  745.         if (single != -1) {
  746.           for (var x = 0; x < this.rowCount; ++x) {
  747.             if (this.data[x].leafName == name) {
  748.               this.selection.select(x);
  749.               this.treebox.ensureRowIsVisible(rowDiff + x - 1 < this.rowCount ? rowDiff + x - 1 : this.rowCount - 1);
  750.               break;
  751.             }
  752.           }
  753.         }
  754.       }
  755.     }
  756.   },
  757.  
  758.   getRecursiveFolderData : function(dir, recursiveFolderData) {
  759.     ++gProcessing;
  760.     gFireFTPUtils.getRecursiveFolderData(dir, new wrapperClass(recursiveFolderData));
  761.     --gProcessing;
  762.   },
  763.  
  764.   // ************************************************* mouseEvent *****************************************************
  765.  
  766.   dblClick : function(event) {
  767.     if (event.button != 0 || event.originalTarget.localName != "treechildren" || this.selection.count == 0) {
  768.       return;
  769.     }
  770.  
  771.     if (this.selection.currentIndex < 0 || this.selection.currentIndex >= this.rowCount) {
  772.       this.selection.currentIndex = this.rowCount - 1;
  773.     }
  774.  
  775.     if (!localFile.verifyExists(this.data[this.selection.currentIndex])) {
  776.       return;
  777.     }
  778.  
  779.     if (this.data[this.selection.currentIndex].isDirectory()) {                                 // if it's a directory
  780.       localDirTree.changeDir(this.data[this.selection.currentIndex].path);                      // navigate to it
  781.     } else {
  782.       if (gOpenMode) {
  783.         this.launch();
  784.       } else {
  785.         new transfer().start(false);                                                            // else upload the file
  786.       }
  787.     }
  788.   },
  789.  
  790.   click : function(event) {
  791.     if (event.button == 1 && !$('localPasteContext').disabled) {                                // middle-click paste
  792.       this.paste();
  793.     }
  794.   },
  795.  
  796.   createContextMenu : function() {
  797.     if (this.selection.currentIndex < 0 || this.selection.currentIndex >= this.rowCount) {
  798.       this.selection.currentIndex = this.rowCount - 1;
  799.     }
  800.  
  801.     for (var x = $('openWithMenu').childNodes.length - 1; x >= 0; --x) {                      // clear out the menu
  802.       $('openWithMenu').removeChild($('openWithMenu').childNodes.item(x));
  803.     }
  804.  
  805.     $('localOpenCont').collapsed    =               this.searchMode != 2;
  806.     $('localOpenContSep').collapsed =               this.searchMode != 2;
  807.     $('localCutContext').setAttribute("disabled",   this.searchMode == 2);
  808.     $('localCopyContext').setAttribute("disabled",  this.searchMode == 2);
  809.     $('localPasteContext').setAttribute("disabled", this.searchMode == 2 || !this.pasteFiles.length);
  810.     $('localCreateDir').setAttribute("disabled",    this.searchMode == 2);
  811.     $('localCreateFile').setAttribute("disabled",   this.searchMode == 2);
  812.  
  813.     if (this.selection.currentIndex == -1) {
  814.       return;
  815.     }
  816.  
  817.     var hasDir = false;
  818.     for (var x = 0; x < this.rowCount; ++x) {
  819.       if (this.selection.isSelected(x)) {
  820.         if (this.data[x].isDirectory()) {
  821.           hasDir = true;
  822.           break;
  823.         }
  824.       }
  825.     }
  826.  
  827.     $('localRecursiveProperties').setAttribute("disabled", !hasDir);
  828.  
  829.     var extension = this.getExtension(this.data[this.selection.currentIndex].leafName);
  830.     var item;
  831.     var found     = false;
  832.  
  833.     var self = this;
  834.     var contextMenuHelper = function(x, y) {
  835.       found = true;
  836.       var program = localFile.init(gPrograms[x].programs[y].executable);
  837.  
  838.       if (!program) {
  839.         return;
  840.       }
  841.  
  842.       var fileURI = gIos.newFileURI(program);
  843.       item        = document.createElement("menuitem");
  844.       item.setAttribute("class",     "menuitem-iconic");
  845.       item.setAttribute("image",     "moz-icon://" + fileURI.spec + "?size=16");
  846.       item.setAttribute("label",     gPrograms[x].programs[y].name);
  847.       item.setAttribute("oncommand", "launchProgram(" + x + ", " + y + ")");
  848.       $('openWithMenu').appendChild(item);
  849.     };
  850.  
  851.     for (var x = 0; x < gPrograms.length; ++x) {
  852.       if (gPrograms[x].extension.toLowerCase() == extension.toLowerCase()) {
  853.         for (var y = 0; y < gPrograms[x].programs.length; ++y) {
  854.           contextMenuHelper(x, y);
  855.         }
  856.  
  857.         break;
  858.       }
  859.     }
  860.  
  861.     for (var x = 0; x < gPrograms.length; ++x) {
  862.       if (gPrograms[x].extension == "*.*") {
  863.         for (var y = 0; y < gPrograms[x].programs.length; ++y) {
  864.           contextMenuHelper(x, y);
  865.         }
  866.  
  867.         break;
  868.       }
  869.     }
  870.  
  871.     if (found) {
  872.       item = document.createElement("menuseparator");
  873.       $('openWithMenu').appendChild(item);
  874.     }
  875.  
  876.     item = document.createElement("menuitem");
  877.     item.setAttribute("label", gStrbundle.getString("chooseProgram"));
  878.     item.setAttribute("oncommand", "chooseProgram()");
  879.     $('openWithMenu').appendChild(item);
  880.  
  881.     var isZippy = extension == "zip" || extension == "jar" || extension == "xpi";
  882.     $('extractHereContext').collapsed = !isZippy;
  883.     $('extractToContext').collapsed   = !isZippy;
  884.   },
  885.  
  886.   mouseOver : function(event) {                                                                 // display local folder info
  887.     if (this.rowCount) {
  888.       $('statustxt').label = gStrbundle.getString("localListing") + " " + gStrbundle.getFormattedString("objects", [this.rowCount])
  889.                            + (this.localSize < 0 ? "" : ", " + commas(this.localSize)) + ", "
  890.                            + gStrbundle.getString("diskSpace")    + " " + this.localAvailableDiskSpace;
  891.     } else {
  892.       $('statustxt').label = gStrbundle.getString("localListingNoObjects");
  893.     }
  894.   },
  895.  
  896.   // ************************************************* keyEvent *****************************************************
  897.  
  898.   keyPress : function(event) {
  899.     if (gLocalTree.editingRow != -1) {
  900.       if (event.keyCode == 27) {
  901.         if (this.editType == "create") {
  902.           this.setCellText(-1, "", "");
  903.         } else {
  904.           this.displayData[gLocalTree.editingRow].leafName = this.displayData[gLocalTree.editingRow].origLeafName;
  905.           this.displayData[gLocalTree.editingRow].path     = this.displayData[gLocalTree.editingRow].origPath;
  906.           this.treebox.invalidateRow(gLocalTree.editingRow);
  907.         }
  908.       }
  909.  
  910.       return;
  911.     }
  912.  
  913.     if (this.selection.currentIndex < 0 || this.selection.currentIndex >= this.rowCount) {
  914.       this.selection.currentIndex = this.rowCount - 1;
  915.     }
  916.  
  917.     var accelKey = testAccelKey(event);
  918.  
  919.     if (event.keyCode == 13 && this.selection.count != 0) {                                     // enter
  920.       if (!localFile.verifyExists(this.data[this.selection.currentIndex])) {
  921.         return;
  922.       }
  923.  
  924.       if (this.selection.count == 1 && this.data[this.selection.currentIndex].isDirectory()) {  // if it's a directory
  925.         localDirTree.changeDir(this.data[this.selection.currentIndex].path);                    // navigate to it
  926.       } else {
  927.         if (gOpenMode) {
  928.           this.launch();
  929.         } else {
  930.           new transfer().start(false);                                                          // else upload a file
  931.         }
  932.       }
  933.     } else if (accelKey && (event.which == 65 || event.which == 97)) {
  934.       event.preventDefault();                                                                   // accel-a: select all
  935.       this.selection.selectAll();
  936.     } else if (event.ctrlKey && event.keyCode == 32 && this.selection.count != 0) {             // ctrl-space, select or deselect
  937.       this.selection.toggleSelect(this.selection.currentIndex);
  938.     } else if (event.keyCode  == 8) {                                                           // backspace
  939.       event.preventDefault();
  940.       localDirTree.cdup();
  941.     } else if (event.keyCode  == 116) {                                                         // F5
  942.       event.preventDefault();
  943.       this.refresh(false, true);
  944.     } else if (event.keyCode  == 113 && this.selection.count != 0) {                            // F2
  945.       this.rename();
  946.     } else if (event.charCode == 100 && accelKey) {                                             // accel-d
  947.       event.preventDefault();
  948.       this.create(true);
  949.     } else if (event.charCode == 110 && accelKey) {                                             // accel-n
  950.       event.preventDefault();
  951.       this.create(false);
  952.     } else if (event.keyCode  == 46 && this.selection.count != 0) {                             // del
  953.       this.remove();
  954.     } else if (event.keyCode  == 93) {                                                          // display context menu
  955.       var x = {};    var y = {};    var width = {};    var height = {};
  956.       this.treebox.getCoordsForCellItem(this.selection.currentIndex, this.treebox.columns["localname"], "text", x, y, width, height);
  957.       this.createContextMenu();
  958.       $('localmenu').showPopup(gLocalTreeChildren, gLocalTreeChildren.boxObject.x + 75, gLocalTreeChildren.boxObject.y + y.value + 5, "context");
  959.     } else if (event.charCode == 112 && accelKey && this.selection.count != 0) {                // accel-p
  960.       event.preventDefault();
  961.       this.showProperties(false);
  962.     } else if (event.charCode == 120 && accelKey && this.selection.count != 0) {                // accel-x
  963.       event.preventDefault();
  964.       this.cut();
  965.     } else if (event.charCode == 99  && accelKey && this.selection.count != 0) {                // accel-c
  966.       event.preventDefault();
  967.       this.copy();
  968.     } else if (event.charCode == 118 && accelKey) {                                             // accel-v
  969.       event.preventDefault();
  970.       this.paste();
  971.     } else if (event.charCode == 111 && accelKey) {                                             // accel-o
  972.       event.preventDefault();
  973.       this.launch();
  974.     }
  975.   },
  976.  
  977.   // ************************************************* cut, copy, paste *****************************************************
  978.  
  979.   isCut      : false,
  980.   pasteFiles : new Array(),
  981.   oldParent  : "",
  982.  
  983.   cut  : function() {
  984.     this.copy(true);
  985.   },
  986.  
  987.   copy : function(isCut) {
  988.     if (this.searchMode == 2) {
  989.       return;
  990.     }
  991.  
  992.     if (this.selection.count == 0) {
  993.       return;
  994.     }
  995.  
  996.     this.isCut      = isCut;
  997.     this.pasteFiles = new Array();
  998.     this.oldParent  = gLocalPath.value;
  999.  
  1000.     for (var x = 0; x < this.rowCount; ++x) {                                                   // put files to be cut/copied in an array to be pasted
  1001.       if (this.selection.isSelected(x)) {
  1002.         if (localFile.verifyExists(this.data[x])) {
  1003.           this.pasteFiles.push(this.data[x]);
  1004.           this.displayData[x].isCut = isCut;
  1005.           this.treebox.invalidateRow(x);
  1006.         }
  1007.       }
  1008.     }
  1009.  
  1010.     $('localPasteContext').setAttribute("disabled", false);                                     // enable pasting
  1011.   },
  1012.  
  1013.   paste : function(dest) {
  1014.     if (this.searchMode == 2) {
  1015.       return;
  1016.     }
  1017.  
  1018.     if (this.pasteFiles.length == 0) {
  1019.       return;
  1020.     }
  1021.  
  1022.     var zeFiles = new Array();
  1023.     for (var x = 0; x < this.pasteFiles.length; ++x) {
  1024.       zeFiles.push(this.pasteFiles[x]);
  1025.     }
  1026.  
  1027.     var newParent = dest ? dest : gLocalPath.value;
  1028.  
  1029.     if (!localFile.verifyExists(zeFiles[0])) {
  1030.       return;
  1031.     }
  1032.  
  1033.     for (var x = 0; x < zeFiles.length; ++x) {
  1034.       var newParentSlash = newParent       + (newParent.charAt(newParent.length - 1)             != gSlash ? gSlash : '');
  1035.       var pasteFileSlash = zeFiles[x].path + (zeFiles[x].path.charAt(zeFiles[x].path.length - 1) != gSlash ? gSlash : '');
  1036.  
  1037.       if (zeFiles[x].isDirectory() && newParentSlash.indexOf(pasteFileSlash) == 0) {    // can't copy into a subdirectory of itself
  1038.         doAlert(gStrbundle.getString("copySubdirectory"));
  1039.         return;
  1040.       }
  1041.     }
  1042.  
  1043.     var prompt     = true;
  1044.     var skipAll    = false;
  1045.     var anyFolders = false;
  1046.     ++gProcessing;
  1047.  
  1048.     try {
  1049.       var newDir = localFile.init(newParent);
  1050.  
  1051.       for (var x = 0; x < zeFiles.length; ++x) {
  1052.         if (!localFile.verifyExists(zeFiles[x])) {
  1053.           continue;
  1054.         }
  1055.  
  1056.         if (zeFiles[x].isDirectory()) {
  1057.           anyFolders = true;
  1058.         }
  1059.  
  1060.         var newFile = localFile.init(this.constructPath(newDir.path, zeFiles[x].leafName));
  1061.  
  1062.         if (newFile.exists() && skipAll) {
  1063.           continue;
  1064.         }
  1065.  
  1066.         if (newFile.exists() && (newFile.isDirectory() || zeFiles[x].isDirectory())) {
  1067.           error(gStrbundle.getFormattedString("pasteErrorFile", [zeFiles[x].path]));
  1068.           continue;
  1069.         }
  1070.  
  1071.         if (newFile.exists() && prompt) {                                                       // ask nicely
  1072.           var params = { response         : 0,
  1073.                          fileName         : newFile.path,
  1074.                          resume           : true,
  1075.                          replaceResume    : true,
  1076.                          existingSize     : newFile.fileSize,
  1077.                          existingDate     : newFile.lastModifiedTime,
  1078.                          newSize          : zeFiles[x].fileSize,
  1079.                          newDate          : zeFiles[x].lastModifiedTime,
  1080.                          timerEnable      : false };
  1081.  
  1082.           window.openDialog("chrome://fireftp/content/confirmFile.xul", "confirmFile", "chrome,modal,dialog,resizable,centerscreen", params);
  1083.  
  1084.           if (params.response == 2) {
  1085.             prompt = false;
  1086.           } else if (params.response == 3) {
  1087.             continue;
  1088.           } else if (params.response == 4 || params.response == 0) {
  1089.             --gProcessing;
  1090.             return;
  1091.           } else if (params.response == 5) {
  1092.             skipAll = true;
  1093.             continue;
  1094.           }
  1095.         }
  1096.  
  1097.         var innerEx = gFireFTPUtils.cutCopy(this.isCut, zeFiles[x], newFile, newDir, null);
  1098.  
  1099.         if (innerEx) {
  1100.           throw innerEx;
  1101.         }
  1102.       }
  1103.     } catch (ex) {
  1104.       debug(ex);
  1105.       error(gStrbundle.getString("pasteError"));
  1106.     } finally {
  1107.       --gProcessing;
  1108.     }
  1109.  
  1110.     var currentDir = dest ? this.oldParent : newParent;
  1111.  
  1112.     if (this.isCut && anyFolders) {
  1113.       var refreshIndex = dest ? localDirTree.indexOfPath(newParent) : localDirTree.indexOfPath(this.oldParent);
  1114.  
  1115.       if (refreshIndex != -1) {
  1116.         if (localDirTree.data[refreshIndex].open) {
  1117.           localDirTree.toggleOpenState(refreshIndex, true);                                     // close it up
  1118.           localDirTree.data[refreshIndex].children = null;                                      // reset its children
  1119.           localDirTree.toggleOpenState(refreshIndex);                                           // and open it up again
  1120.         } else {
  1121.           localDirTree.data[refreshIndex].children = null;                                      // reset its children
  1122.           localDirTree.data[refreshIndex].empty    = false;
  1123.           localDirTree.treebox.invalidateRow(refreshIndex);
  1124.         }
  1125.  
  1126.         if (currentDir == gLocalPath.value) {
  1127.           var refreshIndex2 = localDirTree.indexOfPath(currentDir);
  1128.  
  1129.           if (refreshIndex2 == -1) {
  1130.             localDirTree.changeDir(currentDir);
  1131.           } else {
  1132.             localDirTree.selection.select(refreshIndex2);
  1133.           }
  1134.         }
  1135.       } else {
  1136.         localDirTree.addDirtyList(dest ? newParent : this.oldParent);
  1137.       }
  1138.     }
  1139.  
  1140.     if (this.isCut) {
  1141.       this.pasteFiles  = new Array();
  1142.       this.isCut       = false;
  1143.       $('localPasteContext').setAttribute("disabled", true);
  1144.     }
  1145.  
  1146.     if (currentDir == gLocalPath.value) {                                                       // since we're working on a separate thread make sure we're in the same directory on refresh
  1147.       this.refresh();
  1148.     } else {
  1149.       var path = gLocalPath.value;
  1150.       var refreshIndex = localDirTree.indexOfPath(currentDir);
  1151.  
  1152.       if (refreshIndex != -1) {
  1153.         if (localDirTree.data[refreshIndex].open) {
  1154.           localDirTree.toggleOpenState(refreshIndex, true);                                     // close it up
  1155.           localDirTree.data[refreshIndex].children = null;                                      // reset its children
  1156.           localDirTree.toggleOpenState(refreshIndex);                                           // and open it up again
  1157.         } else {
  1158.           localDirTree.data[refreshIndex].children = null;                                      // reset its children
  1159.           localDirTree.data[refreshIndex].empty    = false;
  1160.           localDirTree.treebox.invalidateRow(refreshIndex);
  1161.         }
  1162.  
  1163.         var refreshIndex2 = localDirTree.indexOfPath(path);
  1164.  
  1165.         if (refreshIndex2 == -1) {
  1166.           localDirTree.changeDir(path);
  1167.         } else {
  1168.           localDirTree.selection.select(refreshIndex2);
  1169.         }
  1170.       } else {
  1171.         localDirTree.addDirtyList(currentDir);
  1172.       }
  1173.     }
  1174.   },
  1175.  
  1176.   canDrop : function(index, orient) {
  1177.     if (!dragObserver.origin || (dragObserver.origin.indexOf('local') != -1 && index == -1) || dragObserver.origin == "external"
  1178.      || (dragObserver.origin.indexOf('local') != -1 && !this.data[index].isDirectory())) {
  1179.       return false;
  1180.     }
  1181.  
  1182.     if (dragObserver.origin == 'localtreechildren') {                                           // don't drag onto itself
  1183.       for (var x = 0; x < this.rowCount; ++x) {
  1184.         if (this.selection.isSelected(x) && index == x) {
  1185.           return false;
  1186.         }
  1187.       }
  1188.     }
  1189.  
  1190.     if (dragObserver.origin.indexOf('remote') != -1 && !gFtp.isConnected) {
  1191.       return false;
  1192.     }
  1193.  
  1194.     return true;
  1195.   },
  1196.  
  1197.   drop : function(index, orient) {
  1198.     if (dragObserver.origin == 'localtreechildren') {
  1199.       this.cut();
  1200.       this.paste(this.data[index].path);
  1201.     } else if (dragObserver.origin == 'remotetreechildren') {
  1202.       if (!dragObserver.overName || index == -1 || !this.data[index].isDirectory()) {
  1203.         new transfer().start(true);
  1204.       } else {
  1205.         var transferObj          = new transfer();
  1206.         transferObj.localRefresh = gLocalPath.value;
  1207.         transferObj.start(true,  '', this.data[index].path, '');
  1208.       }
  1209.     }
  1210.   }
  1211. };
  1212.